package persistence

import (
	"fmt"
	"log"
	"pushserver/serialize"

	"github.com/garyburd/redigo/redis"
)

const (
	userMsgPrifix = "u_m_"
)

type RedisOptions struct {
	Address  string
	Network  string
	Password string
}

type RedisContainer struct {
	option     *RedisOptions
	serializer serialize.Serialize
}

func (this *RedisContainer) try() {
	c, err := this.dial()
	if err != nil {
		panic(fmt.Sprintf("redis conn error: %s", err))
	}
	defer c.Close()

}
func (this *RedisContainer) dial() (redis.Conn, error) {
	var op = make([]redis.DialOption, 0)
	if this.option.Password != "" {
		op = append(op, redis.DialPassword(this.option.Password))
	}
	return redis.Dial(this.option.Network, this.option.Address, op...)
}

func (this *RedisContainer) Get(id string) (*OfflineMsg, error) {
	c, err := this.dial()
	if err != nil {
		return nil, err
	}
	defer c.Close()

	jsonStr, err := redis.String(c.Do("GET", id))
	if err != nil {
		return nil, err
	}

	msg := new(OfflineMsg)
	if err = this.serializer.Decode([]byte(jsonStr), msg); err != nil {
		return nil, err
	}
	c.Do("DEL", id)
	return msg, nil
}

func (this *RedisContainer) GetUserMsg(userID string) ([]*OfflineMsg, error) {
	c, err := this.dial()
	if err != nil {
		return nil, err
	}
	defer c.Close()

	msgs, err := redis.Values(c.Do("SMEMBERS", userMsgPrifix+userID))
	if err != nil {
		return nil, err
	}

	result := make([]*OfflineMsg, 0)

	for _, k := range msgs {
		id, _ := redis.String(k, nil)
		jsonStr, err := redis.String(c.Do("GET", id))
		if err == nil {
			msg := new(OfflineMsg)
			if err = this.serializer.Decode([]byte(jsonStr), msg); err == nil {
				result = append(result, msg)
			}
			c.Do("DEL", id)
		}
	}
	c.Do("DEL", userMsgPrifix+userID)
	return result, nil
}

func (this *RedisContainer) Put(msg *OfflineMsg) {
	c, err := this.dial()
	if err != nil {
		log.Printf("offline msg input failed :", err)
	}
	defer c.Close()

	json, _ := this.serializer.Encode(msg)
	c.Do("SET", msg.MsgId, string(json))
	c.Do("SADD", userMsgPrifix+msg.To, msg.MsgId)
}
